package play;

import org.antlr.v4.runtime.ParserRuleContext;

import java.util.List;

public class Class extends Scope implements  Type{

    // 父类
    private Class parentClass = null;

    // this 变量
    private This thisRef = null;

    private Super superRef = null;

    private DefaultConstructor defaultConstructor = null;

    protected Class(String name, ParserRuleContext ctx) {
        this.name = name;
        this.ctx = ctx;
        thisRef = new This(this, ctx);
        thisRef.type = this;
    }

    protected Class getParentClass() {
        return parentClass;
    }

    protected void setParentClass(Class theClass) {
        parentClass = theClass;

        // 其实 superRef引用的也是自己
        superRef = new Super(parentClass, ctx);
        superRef.type = parentClass;
    }

    // 最顶层的基类
    private static Class rootClass = new Class("Object", null);

    public This getThis() {
        return thisRef;
    }

    public Super getSuper() {
        return superRef;
    }

    @Override
    public String toString() {
        return "Class " + name;
    }

    @Override
    public boolean isType(Type type) {
        if (this == type) {
            return true;
        }
        if (type instanceof Class) {
            // 本类的子类
            return ((Class) type).isAncestor(this);
        }
        return false;
    }

    /**
     * 本类型是不是另一个类型的祖先类型
     * @param theClass 另一个类型
     * @return bool
     */
    public boolean isAncestor(Class theClass) {
        if (theClass.getParentClass() != null) {
            if (theClass.getParentClass() == this) {
                return true;
            } else {
                return isAncestor(theClass.getParentClass());
            }
        }
        return false;
    }

    /**
     * 是否包含某个 Variable， 包括自身及父类
     * @param name 变量名
     * @return 变量
     */
    @Override
    protected Variable getVariable(String name) {
        Variable rtn = super.getVariable(name);
        if (rtn == null && parentClass != null) {
            // 查找父类，是否需要检查 visibility ?
            rtn = parentClass.getVariable(name);
        }
        return rtn;
    }

    protected Class getClass(String name) {
        Class rtn = super.getClass(name);
        if (rtn == null && parentClass != null) {
            rtn = parentClass.getClass(name);
        }
        return rtn;
    }

    /**
     * 找到某个构建函数。
     * @param paramTypes 参数列表
     * @return function
     */
    protected Function findConstructor(List<Type> paramTypes) {
        return super.getFunction(name, paramTypes);
    }

    /**
     * 在自身及父类中找到某个方法。
     * @param name name
     * @param paramTypes 参数类型。不允许为空。如果没有参数，需要传入一个空列表
     * @return 函数
     */
    protected Function getFunction(String name, List<Type> paramTypes) {
        Function rtn = super.getFunction(name, paramTypes);

        if (rtn == null && parentClass != null) {
            rtn = parentClass.getFunction(name, paramTypes);
        }
        return rtn;
    }

    protected Variable getFunctionVariable(String name, List<Type> paramTypes) {
        Variable rtn = super.getFunctionVariable(name, paramTypes);
        if (rtn == null && parentClass != null) {
            rtn = parentClass.getFunctionVariable(name, paramTypes);
        }
        return rtn;
    }

    /**
     * 包含某个 Symbol。此时需要考虑父类
     * @param symbol 符号
     * @return bool
     */
    @Override
    protected boolean containsSymbol(Symbol symbol) {
        if (symbol == thisRef || symbol == superRef) {
            return true;
        }
        boolean rtn = false;
        rtn = symbols.contains(symbol);
        if (!rtn && parentClass != null) {
            rtn = parentClass.containsSymbol(symbol);
        }
        return rtn;
    }

    // 默认构造函数
    protected DefaultConstructor defaultConstructor() {
        if (defaultConstructor == null) {
            defaultConstructor = new DefaultConstructor(this.name, this);
        }
        return defaultConstructor;
    }
}
